"""辅助流程工具。

提供一个安全的 run() 协调函数，用于非破坏性地检查配置与数据加载。
该函数不会写入磁盘，仅尝试读取 `config.yaml` 并调用 `src.core_utils.load_data()`（若可用）。
"""

from pathlib import Path
from typing import Tuple, Optional, Callable

import pandas as pd


def _copy_dataframe(df):
	try:
		return df.copy()
	except Exception:
		return df


def merge_geo_population(
	geo,
	pop_df_year,
	merge_on_code: Optional[str] = None,
	name_suffixes: Optional[list] = None,
	normalize_name_fn: Optional[Callable[[str], str]] = None,
):
	"""将人口数据合并到 geo 并返回 GeoDataFrame。

	策略：优先使用 town_code（merge_on_code），否则尝试基于名称字段合并，最后退回到 geo.copy()
	返回值：merged GeoDataFrame，保证存在 '总人口' 列且为数值。
	"""
	geo_df = _copy_dataframe(geo)
	pop_df = _copy_dataframe(pop_df_year)

	try:
		merged = None
		# 优先使用 town_code
		if merge_on_code and 'town_code' in geo_df.columns and merge_on_code in pop_df.columns:
			# 尽量把人口表中除时间/索引外的有用列一并合并进来（例如 mean 等），而不仅仅是 '总人口'
			cols_to_include = [c for c in pop_df.columns if c != merge_on_code]
			# 确保至少包含一个值列
			if not cols_to_include:
				cols_to_include = ['总人口'] if '总人口' in pop_df.columns else []
			codes = pop_df[[merge_on_code] + cols_to_include].drop_duplicates(merge_on_code).copy()
			codes[merge_on_code] = codes[merge_on_code].astype(str)
			merged = geo_df.merge(codes, left_on='town_code', right_on=merge_on_code, how='left')
		else:
			# 名称字段匹配：优先使用已创建的 town_name，其次尝试常见中文字段
			name_field = None
			for cand in ('town_name', '乡', '乡镇', '名称'):
				if cand in geo_df.columns:
					name_field = cand
					break
			if name_field is not None and '乡镇' in pop_df.columns:
				# 包含人口表中与乡镇关联的所有列（如 mean）
				cols_to_include = [c for c in pop_df.columns if c != '乡镇']
				if not cols_to_include:
					cols_to_include = ['总人口'] if '总人口' in pop_df.columns else []
				df_pop = pop_df[['乡镇'] + cols_to_include].drop_duplicates('乡镇').copy()
				if normalize_name_fn is not None:
					geo_df['_merge_name_norm'] = geo_df[name_field].astype(str).map(normalize_name_fn)
					df_pop['_merge_name_norm'] = df_pop['乡镇'].astype(str).map(normalize_name_fn)
					merged = geo_df.merge(df_pop, on='_merge_name_norm', how='left')
					merged = merged.drop(columns=['_merge_name_norm'])
				else:
					merged = geo_df.merge(df_pop, left_on=name_field, right_on='乡镇', how='left')
			else:
				merged = geo_df.copy()

		# 确保总人口列存在且为数值型
		if '总人口' not in merged.columns:
			merged['总人口'] = 0
		else:
			try:
				merged['总人口'] = pd.to_numeric(merged['总人口'], errors='coerce').fillna(0)
			except Exception:
				merged['总人口'] = merged['总人口'].fillna(0)
		return merged
	except Exception:
		m = geo_df.copy()
		if '总人口' not in m.columns:
			m['总人口'] = 0
		return m

def run() -> Tuple[bool, str]:
	"""Run a safe check: read config and attempt to load data.

	Returns (success, message).
	"""
	try:
		repo_root = Path(__file__).resolve().parents[1]
		cfg_path = repo_root / 'config.yaml'
		if not cfg_path.exists():
			return False, 'config.yaml not found'
		# lazy import core_utils
		try:
			from src.core_utils import load_data
		except Exception:
			return False, 'src.core_utils.load_data not available'

		try:
			df = load_data()
			rows = len(df)
			cols = len(df.columns)
			msg = f'load_data 成功，rows={rows} cols={cols}'
			print(msg)
			return True, msg
		except FileNotFoundError as e:
			msg = f'load_data 未找到文件：{e}'
			print(msg)
			return False, msg
		except Exception as e:
			msg = f'load_data 出错：{e}'
			print(msg)
			return False, msg
	except Exception as e:
		return False, str(e)
